]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
screenshot: Move HAVE_RECORDER check into screencast service
authorFlorian Müllner <fmuellner@gnome.org>
Wed, 19 Oct 2022 10:43:29 +0000 (12:43 +0200)
committerFlorian Müllner <fmuellner@gnome.org>
Fri, 4 Nov 2022 09:51:20 +0000 (09:51 +0000)
Some gstreamer plugins require a connection to the display server,
so if we end up initializing gstreamer before we are ourselves
fully initialized, we may end up with a locked compositor.

Avoid this by moving the runtime recorder check into the screencast
D-Bus service, so that all gstreamer calls happen out of process.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/5710

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2519>

data/dbus-interfaces/org.gnome.Shell.Screencast.xml
js/dbusServices/screencast/main.js
js/dbusServices/screencast/screencastService.js
js/misc/config.js.in
js/ui/screenshot.js

index f188cf72dedd60c5ee52c9ac49eaa56310322589..b4cd592ab1299745f26daed70e382002a5803cc9 100644 (file)
@@ -10,6 +10,7 @@
       The interface used to record screen contents.
   -->
   <interface name="org.gnome.Shell.Screencast">
+    <property name="ScreencastSupported" type="b" access="read"/>
 
     <!--
         Screencast:
index 0bea967aef89f5ecc054ad50040e5639af3d1433..7c71971fb85b19f281b3cb986a383d7231c2cb62 100644 (file)
@@ -1,13 +1,12 @@
 /* exported main */
 
-const Config = imports.misc.config;
-const { DBusService } = imports.dbusService;
+const {DBusService} = imports.dbusService;
 
 function main() {
-    if (!Config.HAVE_RECORDER)
+    const {ScreencastService} = imports.screencastService;
+    if (!ScreencastService.canScreencast())
         return;
 
-    const { ScreencastService } = imports.screencastService;
     const service = new DBusService(
         'org.gnome.Shell.Screencast',
         new ScreencastService());
index bb53874289abe43eb62cfd877b84bbe417046cc7..7b47da27c0f1738f561747c37503ca4a596ce742 100644 (file)
@@ -258,9 +258,17 @@ var Recorder = class {
 };
 
 var ScreencastService = class extends ServiceImplementation {
+    static canScreencast() {
+        return Gst.init_check(null) &&
+            Gst.ElementFactory.find('pipewiresrc') &&
+            Gst.ElementFactory.find('filesink');
+    }
+
     constructor() {
         super(ScreencastIface, '/org/gnome/Shell/Screencast');
 
+        this._canScreencast = ScreencastService.canScreencast();
+
         Gst.init(null);
         Gtk.init();
 
@@ -280,6 +288,10 @@ var ScreencastService = class extends ServiceImplementation {
             '/org/gnome/Shell/Introspect');
     }
 
+    get ScreencastSupported() {
+        return this._canScreencast;
+    }
+
     _removeRecorder(sender) {
         this._recorders.delete(sender);
         if (this._recorders.size === 0)
index fb0b5eb4f65bc9fd7f27b50d8252230c06c41cad..8ef427037bb8770ebad352d6b04d5fd1adb4ceb5 100644 (file)
@@ -21,8 +21,3 @@ var LIBMUTTER_API_VERSION = '@LIBMUTTER_API_VERSION@'
 
 var HAVE_BLUETOOTH = pkg.checkSymbol('GnomeBluetooth', '3.0',
     'Client.default_adapter_state')
-var HAVE_RECORDER =
-    pkg.checkSymbol('Gst', '1.0') &&
-    imports.gi.Gst.init_check(null) &&
-    imports.gi.Gst.ElementFactory.find('pipewiresrc') &&
-    imports.gi.Gst.ElementFactory.find('filesink');
index d43bf0dc7f11d8a5126c28d3440ae4cdc600f4ee..a01fbe3c94d81a6d8947a6b52d22b2ef33e44700 100644 (file)
@@ -3,7 +3,6 @@
 
 const { Clutter, Cogl, Gio, GObject, GLib, Graphene, Gtk, Meta, Shell, St } = imports.gi;
 
-const Config = imports.misc.config;
 const GrabHelper = imports.ui.grabHelper;
 const Layout = imports.ui.layout;
 const Lightbox = imports.ui.lightbox;
@@ -1019,6 +1018,19 @@ var ScreenshotUI = GObject.registerClass({
 
         this._screencastInProgress = false;
 
+        this._screencastProxy = new ScreencastProxy(
+            Gio.DBus.session,
+            'org.gnome.Shell.Screencast',
+            '/org/gnome/Shell/Screencast',
+            (object, error) => {
+                if (error !== null) {
+                    log('Error connecting to the screencast service');
+                    return;
+                }
+
+                this._castButton.visible = this._screencastProxy.ScreencastSupported;
+            });
+
         this._lockdownSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.lockdown' });
 
         // The full-screen screenshot has a separate container so that we can
@@ -1212,7 +1224,7 @@ var ScreenshotUI = GObject.registerClass({
             style_class: 'screenshot-ui-shot-cast-button',
             icon_name: 'camera-web-symbolic',
             toggle_mode: true,
-            visible: Config.HAVE_RECORDER,
+            visible: false,
         });
         this._castButton.connect('notify::checked',
             this._onCastButtonToggled.bind(this));
@@ -1438,7 +1450,7 @@ var ScreenshotUI = GObject.registerClass({
         if (this._screencastInProgress)
             return;
 
-        if (mode === UIMode.SCREENCAST && !Config.HAVE_RECORDER)
+        if (mode === UIMode.SCREENCAST && !this._screencastProxy.ScreencastSupported)
             return;
 
         this._castButton.checked = mode === UIMode.SCREENCAST;
@@ -1809,7 +1821,7 @@ var ScreenshotUI = GObject.registerClass({
         }
     }
 
-    _startScreencast() {
+    async _startScreencast() {
         if (this._windowButton.checked)
             return; // TODO
 
@@ -1833,61 +1845,40 @@ var ScreenshotUI = GObject.registerClass({
         this.close(true);
 
         // This is a bit awkward because creating a proxy synchronously hangs Shell.
-        const doStartScreencast = async () => {
-            let method =
-                this._screencastProxy.ScreencastAsync.bind(this._screencastProxy);
-            if (w !== -1) {
-                method = this._screencastProxy.ScreencastAreaAsync.bind(
-                    this._screencastProxy, x, y, w, h);
-            }
-
-            try {
-                const [success, path] = await method(
-                    GLib.build_filenamev([
-                        /* Translators: this is the folder where recorded
-                           screencasts are stored. */
-                        _('Screencasts'),
-                        /* Translators: this is a filename used for screencast
-                         * recording, where "%d" and "%t" date and time, e.g.
-                         * "Screencast from 07-17-2013 10:00:46 PM.webm" */
-                        /* xgettext:no-c-format */
-                        _('Screencast from %d %t.webm'),
-                    ]),
-                    {'draw-cursor': new GLib.Variant('b', drawCursor)});
-                if (!success)
-                    throw new Error();
-                this._screencastPath = path;
-            } catch (error) {
-                this._setScreencastInProgress(false);
-                const {message} = error;
-                if (message)
-                    log(`Error starting screencast: ${message}`);
-                else
-                    log('Error starting screencast');
-            }
-        };
+        let method =
+            this._screencastProxy.ScreencastAsync.bind(this._screencastProxy);
+        if (w !== -1) {
+            method = this._screencastProxy.ScreencastAreaAsync.bind(
+                this._screencastProxy, x, y, w, h);
+        }
 
         // Set this before calling the method as the screen recording indicator
         // will check it before the success callback fires.
         this._setScreencastInProgress(true);
 
-        if (this._screencastProxy) {
-            doStartScreencast();
-        } else {
-            new ScreencastProxy(
-                Gio.DBus.session,
-                'org.gnome.Shell.Screencast',
-                '/org/gnome/Shell/Screencast',
-                (object, error) => {
-                    if (error !== null) {
-                        log('Error connecting to the screencast service');
-                        return;
-                    }
-
-                    this._screencastProxy = object;
-                    doStartScreencast();
-                }
-            );
+        try {
+            const [success, path] = await method(
+                GLib.build_filenamev([
+                    /* Translators: this is the folder where recorded
+                       screencasts are stored. */
+                    _('Screencasts'),
+                    /* Translators: this is a filename used for screencast
+                     * recording, where "%d" and "%t" date and time, e.g.
+                     * "Screencast from 07-17-2013 10:00:46 PM.webm" */
+                    /* xgettext:no-c-format */
+                    _('Screencast from %d %t.webm'),
+                ]),
+                {'draw-cursor': new GLib.Variant('b', drawCursor)});
+            if (!success)
+                throw new Error();
+            this._screencastPath = path;
+        } catch (error) {
+            this._setScreencastInProgress(false);
+            const {message} = error;
+            if (message)
+                log(`Error starting screencast: ${message}`);
+            else
+                log('Error starting screencast');
         }
     }